describe("utils", function () {

    describe("sort", function(){

        it("sorting", function () {
            var arr = [1, 4, 3, 10 , 2, 3, 2, 2, 4];

            expect(utils.sort(arr)).toEqual([1, 2, 2, 2, 3, 3, 4, 4, 10]);
            expect(utils.sort(arr, function (a, b) {
                return b-a;
            })).toEqual([10, 4, 4, 3, 3, 2, 2, 2, 1]);
        });

        it ("check called function", function(){

            var spy = sinon.spy(Array.prototype, "sort"),
                arr = [1, 4, 3, 10 , 2, 3, 2, 2, 4];

            utils.sort(arr);
            expect(Array.prototype.sort).toHaveBeenCalled();
            spy.restore();

        });

        it("should throw exception to empty object", function () {

            expect(
                function() {utils.sort({})})
                .toThrow("You need to put array for use method utils.sort");

        });


        it("should throw exception to empty array", function () {

            expect(
                function() {utils.sort([])})
                .toThrow("You need to put array for use method utils.sort");

        });

        it("should throw exception to empty string", function () {

            expect(
                function() {utils.sort("")})
                .toThrow("You need to put array for use method utils.sort");

        });

        it("should throw exception to null", function () {

            expect(
                function() {utils.sort(null)})
                .toThrow("You need to put array for use method utils.sort");

        });

        it("should throw exception to undefined", function () {

            expect(
                function() {utils.sort(undefined)})
                .toThrow("You need to put array for use method utils.sort");

        });

    });

    describe("capitalize", function(){

        it("capitalizing", function () {
            var str = "hi man",
                strAfter = "Hi man";
            expect(utils.capitalize(str)).toBe(strAfter);
        });

        it ("check called function", function(){

            var spy = sinon.spy( _.str , "capitalize"),
                str = "hi man";

            utils.capitalize(str);
            expect(_.str.capitalize).toHaveBeenCalled();
            spy.restore();

        });

        it("should throw exception to empty object", function () {

            expect(
                function() {utils.capitalize({})})
                .toThrow("You need to put string for use method utils.capitalize");

        });

        it("should throw exception to null", function () {

            expect(
                function() {utils.capitalize(null)})
                .toThrow("You need to put string for use method utils.capitalize");

        });

        it("should throw exception to undefined", function () {

            expect(
                function() {utils.capitalize(undefined)})
                .toThrow("You need to put string for use method utils.capitalize");

        });

        it("should throw exception to empty string", function () {

            expect(
                function() {utils.capitalize("")})
                .toThrow("You need to put string for use method utils.capitalize");

        });

    });

    describe("camelize", function(){

        it("camelizing", function () {
            var str = "hi man",
                strAfter = "hiMan",
                arr = ["hi man", "hi woman"],
                arrAfter = "hiMan,hiWoman";

            expect(utils.camelize(str)).toBe(strAfter);
            expect(utils.camelize(arr)).toBe(arrAfter);
        });

        it ("check called function", function(){

            var spy = sinon.spy( _.str , "camelize"),
                str = "hi man";

            utils.camelize(str);
            expect(_.str.camelize).toHaveBeenCalled();
            spy.restore();

        });

    });

    describe("trim", function(){

        it("triming", function () {
            var str = "   hi   man  ",
                strAfter = "hi   man";
            expect(utils.trim(str)).toBe(strAfter);
        });

        it ("check called function", function(){

            var spy = sinon.spy( _.str , "trim"),
                str = "   hi  man ";

            utils.camelize(str);
            expect(_.str.trim).toHaveBeenCalled();
            spy.restore();

        });

        it("should throw exception to empty object", function () {

            expect(
                function() {utils.trim({})})
                .toThrow("You need to give string to use utils.trim");

        });

        it("should throw exception to null", function () {

            expect(
                function() {utils.trim(null)})
                .toThrow("You need to give string to use utils.trim");

        });

        it("should throw exception to undefined", function () {

            expect(
                function() {utils.trim(undefined)})
                .toThrow("You need to give string to use utils.trim");

        });

        it("should throw exception to empty string", function () {

            expect(
                function() {utils.trim("")})
                .toThrow("You need to give string to use utils.trim");

        });

    });

    describe("map", function(){

        it("maping array", function () {
            var arr = [1, 2, 3, "1234w"],
                arrAfter = [3, 6, 9, "1234w"],
                func = function (x) {
                    if (!utils.isNumber(x)) return x;
                    return x = (+x)*3;
                };
            expect(utils.map(arr, func)).toEqual(arrAfter);
        });

        it("maping object", function () {
            var obj = { a : "1", b : "2", c : "3", name : "wrt"},
                objAfter = [ '2', '4', '6', 'wrt' ],
                func = function (x) {
                    if (!+x) return x;
                    return x = (+x)*2 + "";
                };
            expect(utils.map(obj, func)).toEqual(objAfter);
        });

        it ("check called function", function(){

            var spy = sinon.spy( _ , "map"),
                obj = { a : "1", b : "2", c : "3", name : "wrt"},
                func = function (x) {
                    if (!+x) return x;
                    return x = (+x)*2 + "";
                };

            utils.map(obj, func);
            expect(_.map).toHaveBeenCalled();
            spy.restore();

        });

    });

    describe("groupBy", function(){

        it("grouping array", function () {
            var arr = [1.3, 1.2, 2.1, 2.4, 2.8],
                objAfter = {1: [1.3, 1.2], 2: [2.1, 2.4, 2.8]},
                func = function(num){ return Math.floor(num)};
            expect(utils.groupBy(arr, func)).toEqual(objAfter);
        });

        it ("check called function", function(){

            var spy = sinon.spy( _ , "groupBy"),
                arr = [1.3, 1.2, 2.1, 2.4, 2.8],
                func = function(num){ return Math.floor(num)};

            utils.groupBy(arr, func)
            expect(_.groupBy).toHaveBeenCalled();
            spy.restore();

        });

        it("should throw exception to empty array", function () {
            expect(
                function() {expect(utils.groupBy([], function(num){ return Math.floor(num)}))})
                .toThrow("You need to put array for use method utils.groupBy");
        });

        it("should throw exception to undefined", function () {
            expect(
                function() {expect(utils.groupBy(undefined, function(num){ return Math.floor(num)}))})
                .toThrow("You need to put array for use method utils.groupBy");
        });

        it("should throw exception to null", function () {
            expect(
                function() {expect(utils.groupBy(null, function(num){ return Math.floor(num)}))})
                .toThrow("You need to put array for use method utils.groupBy");
        });

    });
});
